package com.eshop.modules.activity.service.impl;

import java.lang.invoke.SerializedLambda;
import java.io.IOException;
import com.eshop.utils.FileUtil;
import javax.servlet.http.HttpServletResponse;
import com.eshop.common.utils.QueryHelpPlus;
import com.eshop.modules.user.domain.ShopUser;
import com.eshop.modules.activity.service.dto.StorePinkDto;
import com.github.pagehelper.PageInfo;
import org.springframework.data.domain.Pageable;
import com.eshop.modules.activity.service.dto.StorePinkQueryCriteria;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Collection;
import com.eshop.modules.activity.vo.StorePinkQueryVo;
import java.util.Map;
import java.util.LinkedHashMap;
import com.eshop.modules.activity.service.dto.PinkAllDto;
import com.eshop.modules.activity.service.dto.PinkDto;
import java.util.concurrent.TimeUnit;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.date.DateUtil;
import com.eshop.modules.cart.vo.StoreCartQueryVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.eshop.modules.activity.domain.StoreCombination;
import com.eshop.modules.order.vo.StoreOrderQueryVo;
import com.eshop.modules.user.vo.UserQueryVo;
import com.eshop.modules.activity.vo.StoreCombinationQueryVo;
import java.util.Iterator;
import com.eshop.modules.cart.domain.StoreCart;
import java.io.Serializable;
import com.eshop.enums.PinkEnum;
import com.eshop.modules.activity.vo.PinkInfoVo;
import java.util.ArrayList;
import java.util.List;
import com.eshop.modules.activity.service.dto.PinkUserDto;
import com.eshop.modules.order.domain.StoreOrder;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.util.ObjectUtil;
import com.eshop.api.EshopException;
import java.util.Date;
import com.eshop.enums.OrderInfoEnum;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.eshop.modules.activity.service.StoreVisitService;
import com.eshop.modules.cart.service.StoreCartService;
import com.eshop.modules.user.service.UserService;
import org.springframework.data.redis.core.RedisTemplate;
import com.eshop.modules.order.service.StoreOrderService;
import com.eshop.modules.activity.service.StoreCombinationService;
import com.eshop.modules.activity.service.mapper.StoreCombinationMapper;
import org.springframework.beans.factory.annotation.Autowired;
import com.eshop.dozer.service.IGenerator;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import com.eshop.modules.activity.service.StorePinkService;
import com.eshop.modules.activity.domain.StorePink;
import com.eshop.modules.activity.service.mapper.StorePinkMapper;
import com.eshop.common.service.impl.BaseServiceImpl;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = { Exception.class })
public class StorePinkServiceImpl extends BaseServiceImpl<StorePinkMapper, StorePink> implements StorePinkService
{
    @Autowired
    private IGenerator generator;
    @Autowired
    private StorePinkMapper storePinkMapper;
    @Autowired
    private StoreCombinationMapper storeCombinationMapper;
    @Autowired
    private StoreCombinationService combinationService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserService userService;
    @Autowired
    private StoreCartService storeCartService;
    @Autowired
    private StoreVisitService storeVisitService;
    
    public void removePink(final Long uid, final Long cid, final Long pinkId) {
        final StorePink pink = (StorePink)(((((((this.lambdaQuery().eq(StorePink::getId, pinkId)).eq(StorePink::getUid, uid)).eq(StorePink::getCid, cid)).eq(StorePink::getKId, 0)).eq(StorePink::getIsRefund, OrderInfoEnum.PINK_REFUND_STATUS_0.getValue())).eq(StorePink::getStatus, OrderInfoEnum.REFUND_STATUS_1.getValue())).gt(StorePink::getStopTime, new Date())).one();
        if (pink == null) {
            throw new EshopException("拼团不存在或已经取消");
        }
        final PinkUserDto pinkUserDto = this.getPinkMemberAndPinK(pink);
        final List<StorePink> pinkAll = pinkUserDto.getPinkAll();
        final StorePink pinkT = pinkUserDto.getPinkT();
        final List<Long> idAll = pinkUserDto.getIdAll();
        final List<Long> uidAll = pinkUserDto.getUidAll();
        final int count = pinkUserDto.getCount();
        if (count < 1) {
            this.pinkComplete(uidAll, idAll, uid, pinkT);
            throw new EshopException("拼团已完成，无法取消");
        }
        StorePink nextPinkT = null;
        if (pinkAll.size() > 0) {
            nextPinkT = pinkAll.get(0);
        }
        this.storeOrderService.orderApplyRefund("", "", "拼团取消开团", pinkT.getOrderId(), pinkT.getUid());
        this.orderPinkFailAfter(pinkT.getUid(), pinkT.getId());
        if (ObjectUtil.isNotNull(nextPinkT)) {
            final LambdaQueryWrapper<StorePink> wrapperO = (LambdaQueryWrapper<StorePink>)new LambdaQueryWrapper();
            final StorePink storePinkO = new StorePink();
            storePinkO.setKId(0L);
            storePinkO.setStatus(OrderInfoEnum.PINK_STATUS_1.getValue());
            storePinkO.setStopTime(pinkT.getStopTime());
            storePinkO.setId(nextPinkT.getId());
            this.storePinkMapper.updateById(storePinkO);
            wrapperO.eq(StorePink::getKId, pinkT.getId());
            final StorePink storePinkT = new StorePink();
            storePinkT.setKId(nextPinkT.getId());
            this.storePinkMapper.update(storePinkT, (Wrapper)wrapperO);
            final StoreOrder storeOrder = new StoreOrder();
            storeOrder.setPinkId(nextPinkT.getId());
            storeOrder.setId(nextPinkT.getId());
            this.storeOrderService.updateById(storeOrder);
        }
    }
    
    public int surplusPeople(final StorePink pink) {
        List<StorePink> listT = new ArrayList<StorePink>();
        if (pink.getKId() > 0L) {
            listT = this.getPinkMember(pink.getKId());
        }
        else {
            listT = this.getPinkMember(pink.getId());
        }
        return pink.getPeople() - (listT.size() + 1);
    }
    
    public PinkInfoVo pinkInfo(final Long id, final Long uid) {
        final StorePink pink = this.getPinkUserOne(id);
        if (ObjectUtil.isNull(pink)) {
            throw new EshopException("拼团不存在");
        }
        if (OrderInfoEnum.PINK_REFUND_STATUS_1.getValue().equals(pink.getIsRefund())) {
            throw new EshopException("订单已退款");
        }
        int isOk = 0;
        int userBool = 0;
        int pinkBool = 0;
        final PinkUserDto pinkUserDto = this.getPinkMemberAndPinK(pink);
        final StorePink pinkT = pinkUserDto.getPinkT();
        final List<StorePink> pinkAll = pinkUserDto.getPinkAll();
        final List<Long> idAll = pinkUserDto.getIdAll();
        final List<Long> uidAll = pinkUserDto.getUidAll();
        int count = pinkUserDto.getCount();
        if (count < 0) {
            count = 0;
        }
        if (OrderInfoEnum.PINK_STATUS_2.getValue().equals(pinkT.getStatus())) {
            pinkBool = PinkEnum.PINK_BOOL_1.getValue();
            isOk = PinkEnum.IS_OK_1.getValue();
        }
        else if (pinkT.getStatus() == 3) {
            pinkBool = PinkEnum.PINK_BOOL_MINUS_1.getValue();
            isOk = PinkEnum.IS_OK_0.getValue();
        }
        else if (count < 1) {
            isOk = PinkEnum.IS_OK_1.getValue();
            pinkBool = this.pinkComplete(uidAll, idAll, uid, pinkT);
        }
        else {
            pinkBool = this.pinkFail(pinkAll, pinkT, pinkBool);
        }
        if (ObjectUtil.isNotNull(pinkAll)) {
            for (final StorePink storePink : pinkAll) {
                if (storePink.getUid().equals(uid)) {
                    userBool = PinkEnum.USER_BOOL_1.getValue();
                }
            }
        }
        if (pinkT.getUid().equals(uid)) {
            userBool = PinkEnum.USER_BOOL_1.getValue();
        }
        final StoreCombinationQueryVo storeCombinationQueryVo = this.storeCombinationMapper.getCombDetail(pink.getCid());
        if (ObjectUtil.isNull(storeCombinationQueryVo)) {
            throw new EshopException("拼团不存在或已下架");
        }
        final UserQueryVo userInfo = this.userService.getYxUserById(uid);
        final StoreOrder storeOrder = (StoreOrder)this.storeOrderService.getById((Serializable)pink.getOrderIdKey());
        final StoreCart storeCart = (StoreCart)this.storeCartService.getById((Serializable)storeOrder.getCartId());
        this.storeCombinationMapper.incBrowseNum(pink.getPid());
        this.storeVisitService.addStoreVisit(uid, pink.getPid());
        return PinkInfoVo.builder().count(count).currentPinkOrder(this.getCurrentPinkOrderId(id, uid)).isOk(isOk).pinkAll(this.handPinkAll(pinkAll)).pinkBool(pinkBool).pinkT(this.handPinkT(pinkT)).storeCombination(storeCombinationQueryVo).userBool(userBool).userInfo(userInfo).uniqueId(storeCart.getProductAttrUnique()).build();
    }
    
    public int pinkIngCount(final Long id) {
        return ((this.lambdaQuery().eq(StorePink::getId, id)).eq(StorePink::getStatus, OrderInfoEnum.PINK_STATUS_1.getValue())).count();
    }
    
    public void createPink(StoreOrderQueryVo order) {
        final StoreCombination storeCombination = (StoreCombination)this.combinationService.getById((Serializable)order.getCombinationId());
        order = this.storeOrderService.handleOrder(order);
        final StoreCart storeCart = (StoreCart)this.storeCartService.getById((Serializable)order.getCartId());
        final int pinkCount = this.storePinkMapper.selectCount(Wrappers.<StorePink>lambdaQuery().eq(StorePink::getOrderId, order.getOrderId()));
        if (pinkCount > 0) {
            return;
        }
        if (storeCombination != null) {
            final StorePink storePink = StorePink.builder().uid(order.getUid()).orderId(order.getOrderId()).orderIdKey(order.getId()).totalNum(order.getTotalNum()).totalPrice(order.getPayPrice()).build();
            final List<StoreCartQueryVo> cartInfo = order.getCartInfo();
            for (final StoreCartQueryVo queryVo : cartInfo) {
                storePink.setCid(queryVo.getCombinationId());
                storePink.setPid(queryVo.getProductId());
                storePink.setPrice(queryVo.getProductInfo().getPrice());
            }
            final Date stopTime = (Date)DateUtil.offsetHour(new Date(), (int)storeCombination.getEffectiveTime());
            storePink.setPeople(storeCombination.getPeople());
            storePink.setStopTime(stopTime);
            storePink.setUniqueId(storeCart.getProductAttrUnique());
            if (order.getPinkId() > 0L) {
                if (this.getIsPinkUid(order.getPinkId(), order.getUid())) {
                    return;
                }
                storePink.setKId(order.getPinkId());
                storePink.setStopTime(null);
                this.save(storePink);
                final PinkUserDto pinkUserDto = this.getPinkMemberAndPinK(storePink);
                final StorePink pinkT = pinkUserDto.getPinkT();
                if (OrderInfoEnum.PINK_STATUS_1.getValue().equals(pinkT.getStatus())) {
                    if (pinkUserDto.getCount() == 0) {
                        this.pinkComplete(pinkUserDto.getUidAll(), pinkUserDto.getIdAll(), order.getUid(), pinkT);
                    }
                    else {
                        this.pinkFail(pinkUserDto.getPinkAll(), pinkT, PinkEnum.PINK_BOOL_0.getValue());
                    }
                }
            }
            else {
                this.save(storePink);
                final StoreOrder storeOrder = new StoreOrder();
                storeOrder.setPinkId(storePink.getId());
                storeOrder.setId(order.getId());
                this.storeOrderService.updateById(storeOrder);
                final String redisKey = String.valueOf(StrUtil.format((CharSequence)"{}{}", new Object[] { "pink:cancel:", storePink.getId() }));
                final long expireTime = storeCombination.getEffectiveTime() * 3600L;
                this.redisTemplate.opsForValue().set(redisKey, "1", expireTime, TimeUnit.SECONDS);
            }
        }
    }
    
    public boolean getIsPinkUid(final Long id, final Long uid) {
        //查询store_pink表，该用户拼团正常且pinkId与id对应的上的
        final int count = (((this.<StorePink>lambdaQuery().eq(StorePink::getIsRefund, OrderInfoEnum.PINK_REFUND_STATUS_0.getValue())).eq(StorePink::getUid, uid)).and(i -> ((i.eq(StorePink::getKId, id)).or()).eq(StorePink::getId, id))).count();
        return count > 0;
    }
    
    public int getPinkOkSumTotalNum() {
        return this.storePinkMapper.sumNum();
    }
    
    public List<String> getPinkOkList(final Long uid) {
        final List<String> list = new ArrayList<String>();
        final List<PinkDto> pinkDTOList = this.storePinkMapper.getPinkOkList(uid);
        for (final PinkDto pinkDTO : pinkDTOList) {
            list.add(pinkDTO.getNickname() + "拼团成功");
        }
        return list;
    }
    
    public PinkAllDto getPinkAll(final Long cid) {
        final Map<String, Object> map = new LinkedHashMap<String, Object>(2);
        final List<PinkDto> list = this.storePinkMapper.getPinks(cid);
        final List<Long> pindAll = new ArrayList<Long>();
        for (final PinkDto pinkDto : list) {
            pinkDto.setCount(String.valueOf(this.getPinkPeople(pinkDto.getId(), pinkDto.getPeople())));
            final Date date = pinkDto.getStopTime();
            pinkDto.setH(String.valueOf(DateUtil.hour(date, true)));
            pinkDto.setI(String.valueOf(DateUtil.minute(date)));
            pinkDto.setS(String.valueOf(DateUtil.second(date)));
            pindAll.add(pinkDto.getId());
        }
        return PinkAllDto.builder().list(list).pindAll(pindAll).build();
    }
    
    private List<StorePinkQueryVo> handPinkAll(final List<StorePink> pinkAll) {
        final List<StorePinkQueryVo> list = (List<StorePinkQueryVo>)this.generator.convert((List)pinkAll, (Class)StorePinkQueryVo.class);
        for (final StorePinkQueryVo queryVo : list) {
            final UserQueryVo userQueryVo = this.userService.getYxUserById((long)queryVo.getUid());
            queryVo.setAvatar(userQueryVo.getAvatar());
            queryVo.setNickname(userQueryVo.getNickname());
        }
        return list;
    }
    
    private StorePinkQueryVo handPinkT(final StorePink pinkT) {
        final StorePinkQueryVo pinkQueryVo = (StorePinkQueryVo)this.generator.convert(pinkT, (Class)StorePinkQueryVo.class);
        final UserQueryVo userQueryVo = this.userService.getYxUserById((long)pinkQueryVo.getUid());
        pinkQueryVo.setAvatar(userQueryVo.getAvatar());
        pinkQueryVo.setNickname(userQueryVo.getNickname());
        return pinkQueryVo;
    }
    
    private String getCurrentPinkOrderId(final Long id, final Long uid) {
        StorePink pink = (StorePink)this.storePinkMapper.selectOne((Wrapper)(Wrappers.<StorePink>lambdaQuery().eq(StorePink::getId, id)).eq(StorePink::getUid, uid));
        if (pink == null) {
            pink = (StorePink)this.storePinkMapper.selectOne((Wrapper)(Wrappers.<StorePink>lambdaQuery().eq(StorePink::getKId, id)).eq(StorePink::getUid, uid));
            if (pink == null) {
                return "";
            }
        }
        return pink.getOrderId();
    }
    
    private List<StorePink> getPinkMember(final Long kid) {
        return (List<StorePink>)(((this.lambdaQuery().eq(StorePink::getKId, kid)).eq(StorePink::getIsRefund, OrderInfoEnum.PINK_REFUND_STATUS_0.getValue())).orderByAsc(StorePink::getId)).list();
    }
    
    private StorePink getPinkUserOne(final Long id) {
        return (StorePink)(this.lambdaQuery().eq(StorePink::getId, id)).one();
    }
    
    private boolean getPinkStatus(final List<Long> idAll) {
        final int count = ((this.lambdaQuery().in(StorePink::getId, (Collection)idAll)).eq(StorePink::getIsRefund, OrderInfoEnum.PINK_REFUND_STATUS_1.getValue())).count();
        return count == 0;
    }
    
    private int pinkComplete(final List<Long> uidAll, final List<Long> idAll, final Long uid, final StorePink pinkT) {
        final boolean pinkStatus = this.getPinkStatus(idAll);
        int pinkBool = PinkEnum.PINK_BOOL_0.getValue();
        if (pinkStatus) {
            final LambdaQueryWrapper<StorePink> wrapper = (LambdaQueryWrapper<StorePink>)new LambdaQueryWrapper();
            wrapper.in(StorePink::getId, (Collection)idAll);
            final StorePink storePink = new StorePink();
            storePink.setStopTime(new Date());
            storePink.setStatus(OrderInfoEnum.PINK_STATUS_2.getValue());
            this.update(storePink, (Wrapper)wrapper);
            if (uidAll.contains(uid)) {
                pinkBool = PinkEnum.PINK_BOOL_1.getValue();
            }
        }
        return pinkBool;
    }
    
    private void orderPinkFailAfter(final Long uid, final Long pid) {
        final StorePink storePink = new StorePink();
        final LambdaQueryWrapper<StorePink> wrapper = (LambdaQueryWrapper<StorePink>)new LambdaQueryWrapper();
        wrapper.eq(StorePink::getId, pid);
        storePink.setStatus(OrderInfoEnum.PINK_STATUS_3.getValue());
        storePink.setStopTime(new Date());
        this.storePinkMapper.update(storePink, (Wrapper)wrapper);
        final LambdaQueryWrapper<StorePink> wrapperT = (LambdaQueryWrapper<StorePink>)new LambdaQueryWrapper();
        wrapperT.eq(StorePink::getKId, pid);
        this.storePinkMapper.update(storePink, (Wrapper)wrapperT);
    }
    
    private int pinkFail(final List<StorePink> pinkAll, final StorePink pinkT, int pinkBool) {
        final Date now = new Date();
        if (DateUtil.compare(pinkT.getStopTime(), now) < 0) {
            pinkBool = PinkEnum.PINK_BOOL_MINUS_1.getValue();
            pinkAll.add(pinkT);
            for (final StorePink storePink : pinkAll) {
                this.storeOrderService.orderApplyRefund("", "", "拼团时间超时", storePink.getOrderId(), storePink.getUid());
                this.orderPinkFailAfter(pinkT.getUid(), storePink.getId());
            }
        }
        return pinkBool;
    }
    
    private PinkUserDto getPinkMemberAndPinK(final StorePink pink) {
        List<StorePink> pinkAll = null;
        StorePink pinkT = null;
        if (pink.getKId() > 0L) {
            pinkAll = this.getPinkMember(pink.getKId());
            pinkT = this.getPinkUserOne(pink.getKId());
        }
        else {
            pinkAll = this.getPinkMember(pink.getId());
            pinkT = pink;
        }
        final List<Long> idAll = pinkAll.stream().map(StorePink::getId).collect(Collectors.toList());
        final List<Long> uidAll = pinkAll.stream().map(StorePink::getUid).collect(Collectors.toList());
        idAll.add(pinkT.getId());
        uidAll.add(pinkT.getUid());
        final int count = pinkT.getPeople() - (pinkAll.size() + 1);
        return PinkUserDto.builder().pinkAll(pinkAll).pinkT(pinkT).idAll(idAll).uidAll(uidAll).count(count).build();
    }
    
    private int getPinkPeople(final Long kid, final int people) {
        final LambdaQueryWrapper<StorePink> wrapper = (LambdaQueryWrapper<StorePink>)new LambdaQueryWrapper();
        (wrapper.eq(StorePink::getKId, kid)).eq(StorePink::getIsRefund, OrderInfoEnum.PINK_REFUND_STATUS_0.getValue());
        final int count = this.storePinkMapper.selectCount((Wrapper)wrapper) + 1;
        return people - count;
    }
    
    public Map<String, Object> queryAll(final StorePinkQueryCriteria criteria, final Pageable pageable) {
        this.getPage(pageable);
        final PageInfo<StorePink> page = (PageInfo<StorePink>)new PageInfo((List)this.queryAll(criteria));
        final Map<String, Object> map = new LinkedHashMap<String, Object>(2);
        final List<StorePinkDto> storePinkDtos = (List<StorePinkDto>)this.generator.convert(page.getList(), (Class)StorePinkDto.class);
        storePinkDtos.forEach(i -> {
            ShopUser shopUser = (ShopUser)this.userService.getById((Serializable)i.getUid());
            StoreCombination storeCombination = (StoreCombination)this.combinationService.getById((Serializable)i.getCid());
            i.setNickname(shopUser.getNickname());
            i.setPhone(shopUser.getPhone());
            i.setUserImg(shopUser.getAvatar());
            i.setProduct(storeCombination.getTitle());
            i.setImage(storeCombination.getImage());
            i.setCountPeople(this.count(Wrappers.<StorePink>lambdaQuery().eq(StorePink::getCid, i.getCid())));
            return;
        });
        map.put("content", storePinkDtos);
        map.put("totalElements", page.getTotal());
        return map;
    }
    
    public List<StorePink> queryAll(final StorePinkQueryCriteria criteria) {
        return (List<StorePink>)((StorePinkMapper)this.baseMapper).selectList((Wrapper)QueryHelpPlus.getPredicate(StorePink.class, criteria));
    }
    
    public void download(final List<StorePinkDto> all, final HttpServletResponse response) throws IOException {
        final List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (final StorePinkDto yxStorePink : all) {
            final Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("用户id", yxStorePink.getUid());
            map.put("订单id 生成", yxStorePink.getOrderId());
            map.put("订单id  数据库", yxStorePink.getOrderIdKey());
            map.put("购买商品个数", yxStorePink.getTotalNum());
            map.put("购买总金额", yxStorePink.getTotalPrice());
            map.put("拼团产品id", yxStorePink.getCid());
            map.put("产品id", yxStorePink.getPid());
            map.put("拼团总人数", yxStorePink.getPeople());
            map.put("拼团产品单价", yxStorePink.getPrice());
            map.put(" stopTime", yxStorePink.getStopTime());
            map.put("团长id 0为团长", yxStorePink.getKId());
            map.put("是否发送模板消息0未发送1已发送", yxStorePink.getIsTpl());
            map.put("是否退款 0未退款 1已退款", yxStorePink.getIsRefund());
            map.put("状态1进行中2已完成3未完成", yxStorePink.getStatus());
            list.add(map);
        }
        FileUtil.downloadExcel((List)list, response);
    }
}
